<?php
/**
 * Action定义
 *
 * @package if
 * @subpackage controller
 * @since 1.0
 */
class IAction extends IObject {
	private $name;
	private $ret;
	private $prefix = "do";
	private $suffix;
	
	/**
	 * 构造
	 *
	 * @param string $name 名称
	 * @since 1.0
	 */
	function __construct($name) {
		$this->name = $name;
	}
	
	/**
	 * 设置名称
	 *
	 * @param string $name 名称
	 * @since 1.0
	 */
	function setName($name) {
		$this->name = $name;
	}
	
	/**
	 * 设置返回值
	 *
	 * @param mixed $ret 返回值
	 * @since 1.0
	 */
	function setRet($ret) {
		$this->ret = $ret;
	}
	
	/**
	 * 取得名称
	 *
	 * @return string
	 * @since 1.0
	 */
	function name() {
		return $this->name;
	}
	
	/**
	 * 取得返回值
	 *
	 * @return mixed
	 * @since 1.0
	 */
	function ret() {
		return $this->ret;
	}
	
	/**
	 * 设置前缀
	 *
	 * @param string $prefix 前缀
	 * @since 1.0
	 */
	function setPrefix($prefix) {
		if (if_is_valid_variable_name($prefix)) {
			throw new IException("error action prefix '{$prefix}'", 0x100001);
		}
		$this->prefix = $prefix;
	}
	
	/**
	 * 设置后缀
	 *
	 * @param string $suffix 后缀
	 * @since 1.0
	 */
	function setSuffix($suffix) {
		if (!if_is_valid_variable_name($suffix)) {
			throw new IException("error action suffix '{$suffix}'", 0x100002);
		}
		$this->suffix = $suffix;
	}
	
	/**
	 * 取得动作对应的控制器中的方法名
	 *
	 * @return string
	 * @since 1.0
	 */
	function method() {
		return $this->prefix . $this->name . $this->suffix;
	}
	
	/**
	 * 更广泛的可以匹配的方法名
	 *
	 * @return array
	 * @since 1.0
	 */
	function methods() {
		return array($this->method(), $this->name);
	}
	
	/**
	 * 判断当前动作名称是否和某个模式相匹配
	 *
	 * $pattern:
	 * -  *
	 * - add,modify,delete
	 * - array("add", "modify", "delete")
	 * - array("*", "except" => array( "delete" )) //v1.1.1 加入
	 * - array("add,modify", "delete")
	 * - array(array("add", "modify"), "delete")
	 * 
	 * v1.1.1把点（.）连接符换成逗号（,），并且不区分大小写，动作可以包含控制器名，比如：
	 * - admin.user.index
	 * 
	 * @param mixed $pattern 模式
	 * @return boolean
	 * @since 1.0
	 */
	function match($pattern) {
		$action = strtolower(__CONTROLLER__ . "." . $this->name);
		if ($pattern == "*") {
			return true;
		}
		if (is_string($pattern)) {
			$patterns = array_map(array($this, "_fullActionCallback"), preg_split("/\s*,\s*/", $pattern));
			return in_array("*", $patterns) || in_array($action, $patterns);
		}
		if (is_array($pattern)) {
			$patterns = array_map(array($this, "_fullActionCallback"), $this->_parsePattern($pattern));
			return in_array("*", $patterns) || in_array($action, $patterns);
		}
		return false;
	}
	
	private function _parsePattern(array $pattern) {
		$except = array();
		if (isset($pattern["except"])) {
			$except = is_array($pattern["except"]) ? $pattern["except"] : preg_split("/\s*,\s*/", $pattern["except"]);
		}
		if (in_array("*", $except) || in_array($this->name, $except)) {
			return array();
		}
		unset($pattern["except"]);
		$patterns = array();
		foreach ($pattern as $action) {
			$patterns = array_merge($patterns, is_array($action) ? $action : preg_split("/\s*,\s*/", $action));
		}
		return $patterns;
	}
	
	private function _fullActionCallback($value) {
		return strtolower(strstr($value, ".") ? $value : __CONTROLLER__ . "." . $value);
	}
}

?>